/* Formetto - Webpyte Form Framework - version 2008-02-08
Written by Nando Florestan; donated to the public domain
This script only depends on strDic.js
*/
q = function(o) {
  if (typeof(o) == 'string')  return document.getElementById(o);
  return o;
};

function pop(obj, prop) {
  var val = obj[prop];
  delete obj[prop];
  return val;
}

Array.prototype.contains = function(searchValue){
  var i = this.length;
  while(i--) if (this[i] == searchValue) return true;
  return false;
}
String.prototype.contains = function(str){
  return (this.indexOf(str) != -1);
}
String.prototype.insertAt = function(str, position) {
  return this.substr(0, position) + str + this.substr(position);
}
String.prototype.trim = function() {
  return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
String.prototype.keepOnlyNumbers = function() {
  // Returns a string containing only the algarisms in this string.
  var cat = "";
  for (var i=0; i < this.length; i++) {
    var c = this.charCodeAt(i);
    if (c > 0x2F && c < 0x3A) cat = cat + this.charAt(i);
  }
  return cat;
}


function isEmpty(o) {
  // The parameter can be an input or a string.
  if (o.value != null)  return o.value.length == 0;
  return o.length == 0;
}

function makeSlug(strOriginal, intMaxLen, strTolerable) {
  // intMaxLen and strTolerable are optional.
  if (strOriginal == null) return "";
  var lower = strOriginal.toLowerCase();
  lower = lower.replace(/ç/g, "c");
  lower = lower.replace(/[ãâäáà]/g, "a");
  lower = lower.replace(/[õôöóò]/g, "o");
  lower = lower.replace(/[ĩîíìï]/g, "i");
  lower = lower.replace(/[üũûúù]/g, "u");
  lower = lower.replace(/[êéèë]/g, "e");
  lower = lower.replace(/[ñń]/g, "n");
  var o = ""; // output string
  var good = "abcdefghijklmnopqrstuvwxyz0123456789-" + strTolerable;
  for (l=0; l < lower.length; l++) {
    if (lower[l] == " ") {
      o += "-";
      continue;
    }
    for (g=0; g < good.length; g++) {
      if (lower[l] == good[g]) {
        o += lower[l];
        break;
      }
    }
  }
  if (intMaxLen) {
    o = o.substr(0, intMaxLen);
    // Do not allow it to end in "-"
    if (o[o.length - 1] == "-") o = o.substr(0, o.length - 1);
  }
  return o;
}

function makeNiceFileName(name, intMaxLen, strTolerable) {
    var ext = ''; // file extension
    name = name.toLowerCase();
    for(i = name.length-1; i--; i < 0) {
        if (name[i] == '.') {
            ext = name.substr(i, name.length - 1);
            name = name.substr(0, i);
            break;
        }
    }
    if (ext=='.jpeg') ext = '.jpg';
    return makeSlug(name, intMaxLen, strTolerable) + ext;
}


inputz = new Object();
inputz.selectionSetRange = function(input, start, end) {
  if (input.setSelectionRange != undefined)  input.setSelectionRange(start, end);
  else {
    var range = input.createTextRange();
    range.collapse(true);
    range.moveStart("character", start);
    range.moveEnd("character", end - start);
    range.select();
  }
}
inputz.selectionGetStart = function(input) {
  if (input.selectionStart != undefined)  return input.selectionStart;
  var range = document.selection.createRange();
  var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
  if (!isCollapsed)  range.collapse(true);
  var b = range.getBookmark();
  return b.charCodeAt(2) - 2;
}
inputz.selectionGetEnd = function(input) {
  if (input.selectionEnd != undefined)  return input.selectionEnd;
  var range = document.selection.createRange();
  var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
  if (!isCollapsed)  range.collapse(false);
  var b = range.getBookmark();
  return b.charCodeAt(2) - 2;
}
inputz.isButton = function(o) {
  return o.type == "submit" || o.type == "button";
}
inputz.isSelect = function(o) {
  return o.tagName == "SELECT";
}
inputz.isText = function(o) {
  return o.tagName=="TEXTAREA" || o.type=="text";
}
inputz.isFieldset = function(o) {
    return o.tagName=="FIELDSET";
}
inputz.isFile = function(o) {
    return o.type == "file";
}
inputz.focusFirst = function(frm, allowButtons) {
  if (frm == null)  var frm = document.forms[0];
  var els = q(frm).elements;
  for (var i=0; i < els.length; i++) {
    var e = els[i];
    if (! allowButtons && inputz.isButton(e))  continue;
    if (inputz.isFieldset(e))  continue; // ignore any fieldsets
    e.focus();
    if (inputz.isText(e))  e.select();
    return;
  }
}

function expandArea(a) {
  var a = q(a);
  //if (inputz.isText(a) && 21 > a.rows)  a.rows = a.rows + 3;
  h = a.offsetHeight + 40;
  if (h < 701)  a.style.height = h + "px";
}
function reduceArea(a) {
  var a = q(a);
  //if (inputz.isText(a) && a.rows > 3)  a.rows = a.rows - 3;
  h = a.offsetHeight - 40;
  if (h > 19)  a.style.height = h + "px";
}


// Declaring and validating forms
// ==============================

function validateEmail(str) {
  var rx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  return rx.test(str);
}

keyFilters = new Object();
keyFilters.getCharCode = function(event) {
  if (!event)  return window.event.keyCode; // IE never passes event to functions
  else         return event.charCode; // standard
  // IE only has *keyCode* but only generates the event for keys that mean Unicode chars.
  // Firefox has *charCode* for Unicode chars and keyCode for all keys.
}
keyFilters.getTarget = function(event) {
  var e = event ? event : window.event;
  return e.target ? e.target : e.srcElement;
}
keyFilters.editKeys = [
   0, // charCode zero means a non-Unicode key has been pressed in Firefox and is avaliable at keyCode.
   8, // BACKSPACE
   9, // TAB
  13, // ENTER
];
keyFilters.isEditKey = function(key) {
  return keyFilters.editKeys.contains(key);
}
keyFilters.isNumber = function(chr) {
  return chr > 0x2F && chr < 0x3A;
}
keyFilters.isLetter = function(chr) {
  return (chr > 96 && chr < 123) || // lowercase
    (chr > 64 && chr < 91) ||  // uppercase
    (chr > 0xBF && chr < 0x2C6); // various accented
}
keyFilters.forNumberField = function(e){
  // Allows typing numbers only.
  // Usage: OnKeyPress="return keyFilters.forNumberField(event);"
  var c = keyFilters.getCharCode(e);
  return keyFilters.isNumber(c) || keyFilters.isEditKey(c);
}
keyFilters.generic = function(e, acceptChar, formatter) {
  var c = keyFilters.getCharCode(e);
  if (keyFilters.isEditKey(c))  return true;
  var input = keyFilters.getTarget(e);
  var place = inputz.selectionGetEnd(input); // remember cursor position
  if (acceptChar(c)) {
    var oldLen = input.value.length;
    var newVal = formatter(input.value.insertAt(String.fromCharCode(c), place));
    if (newVal.length > input.maxLength)  return false;
    input.value = newVal;
    place = place + newVal.length - oldLen;
    inputz.selectionSetRange(input, place, place);
  }
  return false;
}
keyFilters.forCurrencyField = function(e) {
  // The user can only type numbers. The value is formatted as positive currency.
  return keyFilters.generic(e, keyFilters.isNumber, keyFilters.formatCurrency);
}
keyFilters.forDateField = function(e) {
  return keyFilters.generic(e, keyFilters.isNumber, keyFilters.formatDate);
}
keyFilters.forDateTimeField = function(e) {
  return keyFilters.generic(e, keyFilters.isNumber, keyFilters.formatDateTime);
}
keyFilters.forPhoneField = function(e) {
  return keyFilters.generic(e, keyFilters.isNumber, keyFilters.formatPhone);
}
keyFilters.CENTS_DELIMITER = ",";
keyFilters.THOUSAND_SEP = ".";
keyFilters.formatCurrency = function(val) {
  // TODO: This function does not support negative values.
  var str = val.keepOnlyNumbers();
  if (parseFloat(str) == 0)  return "0" + keyFilters.CENTS_DELIMITER + "00";
  if (str.length == 1) return "0" + keyFilters.CENTS_DELIMITER + "0" + str;
  if (str.length == 2) return "0" + keyFilters.CENTS_DELIMITER + str;
  var cents = str.substr(str.length-2,2);
  var dollars = str.substr(0, str.length - 2);
  if (dollars.charAt(0) == "0")  dollars = dollars.substr(1);
  str = dollars.split("").reverse().join("").replace(/(\d{3})/g, "$1" + keyFilters.THOUSAND_SEP).split("").reverse().join("") + keyFilters.CENTS_DELIMITER + cents;
  if (str.charAt(0) == keyFilters.THOUSAND_SEP)  return str.substr(1);
  else return str;
}
keyFilters.formatDate = function(str) {
  // Formats a dd/mm/yyyy date as the user types it
  s = str.keepOnlyNumbers();
  if (s=="") return "";
  if (s.length == 1)  return s;
  if (s.length < 3)  return s + "/";
  if (s.length < 4)  return s.substr(0, 2) + "/" + s.substr(2);
  if (s.length < 5)  return s.substr(0, 2) + "/" + s.substr(2) + "/";
  return s.substr(0, 2) + "/" + s.substr(2,2) + "/" + s.substr(4);
}
keyFilters.formatDateTime = function(str) {
  // Formats a "dd/mm/yyyy hh:mm" datetime as the user types it
  s = str.keepOnlyNumbers();
  if (s.length < 8)  return keyFilters.formatDate(s);
  if (s.length == 8) return keyFilters.formatDate(s) + " ";
  if (s.length < 10) return s.substr(0, 2) + "/" + s.substr(2,2) + "/" + s.substr(4,4) + " " + s.substr(8);
  if (s.length==10) return s.substr(0, 2) + "/" + s.substr(2,2) + "/" + s.substr(4,4) + " " + s.substr(8) + ":";
  return s.substr(0, 2) + "/" + s.substr(2,2) + "/" + s.substr(4,4) + " " + s.substr(8,2) + ":" + s.substr(10);
}
keyFilters.formatPhone = function(str) {
  // Formats a (11)1234-1234 phone number as the user types it
  s = str.keepOnlyNumbers();
  if (s.length==0) return "";
  if (s.length==1) return "(" + s;
  if (s.length==2) return "(" + s + ")";
  if (s.length <6) return "(" + s.substr(0,2) + ")" + s.substr(2);
  if (s.length==6) return "(" + s.substr(0,2) + ")" + s.substr(2) + "-";
  return "(" + s.substr(0,2) + ")" + s.substr(2,4) + "-" + s.substr(6);
}


function copyAttribs(source, dest) {
  if (source == null)  return;
  for (attrib in source) {
    dest[attrib] = source[attrib];
  }
  if (dest.id && ! dest.name)  dest["name"] = dest["id"];
}

function appendChildren(childrenArray, o) {
  var container = q(o);
  for (var i=0; i < childrenArray.length; i++) {
    var el = childrenArray[i];
    if (typeof(el) == "string")  container.innerHTML += el;
    else                         container.appendChild(el);
  }
}



validation = new Object();
validation.complain = function(msg, control) {
  if (control != null)  control.focus();
  alert(msg);
  return false;
}
validation.forDateField = function() {
  var ns = this.value.keepOnlyNumbers();
  if (ns.length < 8)
    return validation.complain(strDic.incompleteField + this.label, this);
  var day  = ns.substr(0,2);
  var month = parseFloat(ns.substr(2,2)) - 1;
  var year = ns.substr(4,4);
  var d = new Date(year, month, day);
  if (d.getMonth() != month)
    return validation.complain(strDic.invalidDate, this);
  return true;
}
validation.forDateTimeField = function() {
  var ns = this.value.keepOnlyNumbers();
  if (ns.length < 12)
    return validation.complain(strDic.incompleteField + this.label, this);
  var day  = ns.substr(0,2);
  var month = parseFloat(ns.substr(2,2)) - 1;
  var year = ns.substr(4,4);
  var hour = ns.substr(8,2);
  var min = ns.substr(10,2);
  var d = new Date(year, month, day, hour, min);
  if (d.getMonth() != month)
    return validation.complain(strDic.invalidDate, this);
  if (d.getHours() != hour )
    return validation.complain(strDic.invalidTime, this);
  return true;
}
validation.forPhoneField = function() {
  if (this.value.keepOnlyNumbers().length < 9)
    return validation.complain(strDic.incompleteField + this.label);
  return true;
}
validation.forEmailField = function() {
  if ( ! validateEmail(this.value))
    return validation.complain(strDic.invalidEmail);
  return true;
}
validation.positiveNonZero = function() {
  if (parseFloat(this.value) > 0)  return true;
  return validation.complain(strDic.mustBePositive + this.label);
}
validation.forDayField = function() {
  var day = parseFloat(this.value);
  if (day > 0 && day < 32)  return true;
  return validation.complain("Dia inválido. Deve ser entre 01 e 31.");
}

function bindElementVisibility(element, input, select, expectedValue) {
  // Altera o *select* para que, quando assumir o valor *expectedValue*, cause o aparecimento de *element* e a atribuição do foco a *input*.
  // Útil para permitir que o usuário escolha "Outros" num combo e então especifique numa textbox.
  // Isto é programação funcional com closures.
  element.style.display = 'none'; // A princípio, *element* fica invisível
  var sel = q(select);
  var inp = q(input);
  sel.needsClarification = function() {
    return this.value == expectedValue;
  }
  sel.onchange = function(e) {
    if (this.needsClarification())  {
      element.style.display = '';
      inp.focus();
    }
    else element.style.display = 'none';
  };
  // O preenchimento de *input* será obrigatório conforme o valor do *select*.
  inp.required = function() {
    return sel.needsClarification();
  }
}

function bindElementActivity(dependent, watched) {
  // Faz com que o controle *dependent* seja habilitado ou desabilitado conforme a textbox *watched* tenha ou não texto.
  var dep = q(dependent);
  var wat = q(watched);
  wat.onkeyup = function(e) {
    dep.disabled = isEmpty(this.value);
  }
  dep.disabled = wat.value == "";
}

function isRequired(input) {
  // O atributo *required* pode ser undefined, ou pode ser uma função, ou um simples boolean...
  if (!input.required) return false;
  if (typeof(input.required) == "function")  return input.required();
  return input.required;
}

function validateFields(fields) {
  for (var i=0; i < fields.length; i++) {
    var field = fields[i];
    // Se for um campo de texto obrigatório e vazio
    if (inputz.isText(field) && isRequired(field) && isEmpty(field) ||
      // Ou se for um select obrigatório e vazio
      inputz.isSelect(field) && isRequired(field) && field.value == "" ||
      // Ou se for um file obrigatório e vazio
      inputz.isFile(field) && isRequired(field) && field.value == "") {
        field.focus();
        if (field.label) var handle = field.label;
        else             var handle = field.name;
        alert(strDic.requiredField + handle + '".');
        return false;
    }
    // Se o campo tiver uma função validate(), chame-a
    if (field.validate != null) {
      // Mas não se for um campo de texto vazio.
      if (inputz.isText(field) && isEmpty(field)) continue;
      try { if (! field.validate())  return false; }
      catch(ex) {
        alert("Exceção: " + ex);
        return false;
      }
    }
  }
  return true;
}

function validateConfirmSend(button, msgConfirm) {
  if ( ! validateFields(button.form.elements))  return false;
  return confirmSend(button, msgConfirm);
}
function confirmSend(button, msgConfirm) {
  if (msgConfirm && ! confirm(msgConfirm))  return false;
  submitOnce(button);
}
function submitOnce(button) {
  button.disabled = true;
  buttonToReenable = button;
  window.setTimeout("reenableButton();", buttonTimeout);
  onunload = reenableButton;
  button.form.submit();
  return false;
}
function reenableButton(e) {
  buttonToReenable.disabled = false;
  //delete buttonToReenable;
}
buttonTimeout = 9999;
